﻿#include "qrcode.h"

Qrcode::Qrcode( QObject* parent ) : QObject( parent ) {
    //  sltQrcodeInit();// 需要创建新线程执行Qrcode则在线程开始的时候再执行init，否则直接使用
}

Point Qrcode::returnQrcodePose() {
    return qrcode_point;
}

int Qrcode::returnQrcodeTagID() {
    return qrcode_tag_id;
}

bool Qrcode::isReadCode() const {
    return is_read_code;
}

void Qrcode::sltQrcodeInit() {
    // qDebug() << "qrcode_currentThreadId()==" << QThread::currentThreadId();
    //  qrcode_com = new SerialPortObj( tr( "二维码" ), Param::qrcode_port_name, Param::qrcode_baud_rate, QSerialPort::EvenParity ); 倍加福得是偶校验
    qrcode_com = new SerialPortObj( tr( "二维码模块" ), Param::qrcode_port_name, Param::qrcode_baud_rate );  //大华无校验
    connect( qrcode_com, SIGNAL( sigReadData( QByteArray ) ), this, SLOT( sltDAHUAQrcodeRecvieData( QByteArray ) ) );
    connect( this, SIGNAL( sigSendData( SerialPortObj*, QByteArray ) ), qrcode_com, SLOT( sltSendData( SerialPortObj*, QByteArray ) ) );
    qrcode_com->init( false );

    if ( qrcode_com->isOpened() ) {
        QTimer* timer50ms = new QTimer();

        connect( timer50ms, SIGNAL( timeout() ), this, SLOT( slt50msTimer() ) );
        timer50ms->start( 50 );
    }
    else {
        emit sigSendTips( "错误，二维码模块串口打开失败" );
    }
}

void Qrcode::slt50msTimer() {
    emit sigSendData( qrcode_com, SensorOrder::QrcodeReadOrder() );

    if ( lose_connect_time++ > 60 ) {
        lose_connect_time = 0;
        emit sigLoseConnect( "二维码模块" );
    }
}

/**
 *@brief sltPFQrcodeRecvieData 倍加福数据解析
 *@param
 *@author
 *@date
 */
void Qrcode::sltPFQrcodeRecvieData( const QByteArray& data ) {
    if ( data.size() != kQrcodeRxLen ) {
        qCritical() << "二维码数据长度异常!";
        return;
    }
    //     emit sigQrcodeReceiveData(data, "qrcode:");
    lose_connect_time = 0;
    if ( ( ( data.at( 1 ) & 0x40 ) == 0x40 ) && ( data.at( kQrcodeRxLen - 1 ) == Utility::BCC( data, kQrcodeRxLen - 2 ) ) )  // tag 可以使用

    {
        if ( data.at( 0 ) & 0x01 ) {
            qCritical() << "二维码模块发生ERR错误!";
            return;
        }

        int tag_id = static_cast< uchar >( data.at( 16 ) * 0x80 ) + static_cast< uchar >( data.at( 17 ) );

        if ( tag_id < Param::qrcode_station_list.size() ) {
            int x = 0, y = 0;
            // x
            int x_position = ( static_cast< uchar >( data.at( 2 ) ) & 0x07 * 0x80 * 0x4000 ) + ( static_cast< uchar >( data.at( 3 ) ) * 0x4000 ) + ( static_cast< uchar >( data.at( 4 ) ) * 0x80 )
                             + static_cast< uchar >( data.at( 5 ) );
            //计算正负
            if ( x_position > 0x800000 ) {
                x = ( 0x1000000 - x_position );
                x = x * ( -1 );
            }
            else {
                x = x_position;
            }
            qDebug() << "坐标数据值!"
                     << "x:" << x << ";";
            // y
            int y_position = ( static_cast< uchar >( data.at( 6 ) ) * 0x80 ) + static_cast< uchar >( data.at( 7 ) );
            //计算正负
            if ( y_position > 0x2000 ) {
                y = ( 0x4000 - y_position );
                y = y * ( -1 );
            }
            else {
                y = y_position;
            }

            //计算角度.当分辨率为0.1度时,ang最大为3600;当分辨率为1度时,ang最大为360
            int ang = static_cast< uchar >( data.at( 10 ) ) * 0x80 + static_cast< uchar >( data.at( 11 ) );

            /********************摄像头Y轴作为车头，摄像头配置软件角度设置为900********************/

            /*  ang = 1800 - ang;    //倍加福弧度是镜像的，这里需要反转一下且将角度从0~360转化成[0，180][-180，0]
          * if (ang == -1800)    //如果出现-180则转为180，目的是区间[0，180](-180，0]
          * {
          *   ang = 1800;
          * }*/
            /********************摄像头X轴作为车头，摄像头配置软件角度设置为0********************/

            ang = 3600 - ang;  //先镜像反转
            if ( ang > 1800 )  //将角度从180~360转化成(-180，0]
            {
                ang = ang - 3600;
            }

            double rad = M_PI * ( static_cast< double >( ang ) ) / 1800;
            //偏差数据计算值异常，除去该数据
            if ( ( abs( x ) > 150 ) || ( abs( y ) > 150 ) ) {
                qCritical() << "坐标数据值异常!"
                            << "x:" << x << ";"
                            << "y:" << y << ";";
                return;
            }

            /**传感器安装不在中心的修正
          *       static double bais_rad_err;
          *       bais_rad_err = qrcode_point.radian() - M_PI_2;
          *       Utility::radianCorrection(&bais_rad_err);
          *       original_qrcode_pose_.setX(x + Param::qrcode_to_mid + Param::qrcode_station_list.at(id)->point()->x());
          *       original_qrcode_pose_.setY(y + Param::qrcode_station_list.at(id)->point()->y());
          *       original_qrcode_pose_.setRadian(rad);
          *       qrcode_point.setRadian(rad);
          *       qrcode_point.setX(original_qrcode_pose_.x() - Param::qrcode_to_mid *cos(bais_rad_err));
          *       qrcode_point.setY(original_qrcode_pose_.y() - Param::qrcode_to_mid *sin(bais_rad_err));*/

            /*使用于AGV 摄像头位置在中心位置前面75mm
          * qrcode_point.setRadian(rad);
          * qrcode_point.setX((x + Param::qrcode_station_list.at(id)->point()->x()) - Param::qrcode_to_mid *cos(rad));
          * qrcode_point.setY((y + Param::qrcode_station_list.at(id)->point()->y()) - Param::qrcode_to_mid *sin(rad));
          */

            //使用于AGV 摄像头位置在中心位置
            qrcode_point.setRadian( rad );
            qrcode_point.setX( x + Param::qrcode_station_list.at( tag_id )->point()->x() );
            qrcode_point.setY( y + Param::qrcode_station_list.at( tag_id )->point()->y() );

            qrcode_tag_id = tag_id;
            //如果不是同一个二维码,那么把二维码id记录下来
            if ( last_qrcode_tag_id != qrcode_tag_id ) {
                qDebug() << tr( "读取二维码 id:%1 x:%2 y:%3 rad:%4" ).arg( tag_id ).arg( qrcode_point.x() ).arg( qrcode_point.y() ).arg( qrcode_point.radian(), 0, 'f', 3 );
            }
            last_qrcode_tag_id = qrcode_tag_id;
            //将计算过好的导航需要的参数数据发送出去
            emit sigQrcodRecvieNaviParam();
        }
    }
}

/**
 *@brief  sltDAHUAQrcodeRecvieData 大华科技二维码解析
 *@param
 *@author
 *@date
 */
void Qrcode::sltDAHUAQrcodeRecvieData( const QByteArray& data ) {

    emit sigQrcodeReceiveData( data, "qrcode:" );

    if ( data.size() != kQrcodeRxLen ) {
        qCritical() << "二维码数据长度异常!";
        return;
    }
    lose_connect_time = 0;
    if ( ( data.at( kQrcodeRxLen - 1 ) != Utility::BCC( data, kQrcodeRxLen - 2 ) ) ) {
        // qCritical() << "二维码数据BCC校验错误!";
        return;
    }

    //判别有无读到码
    if ( ( data.at( 0 ) & 0x02 ) == 0x02 ) {
        is_read_code = false;
        return;
    }
    is_read_code = true;
    short int x  = static_cast< uchar >( data[ 4 ] ) * 0x80 + static_cast< uchar >( data[ 5 ] );
    short int y  = static_cast< uchar >( data[ 6 ] ) * 0x80 + static_cast< uchar >( data[ 7 ] );
    /*if ( x > 0x80 ) {
        //负数
        x += 0xc000;
    }
    if ( y > 0x80 ) {
        //负数
        y += 0xc000;
    }*/
    if ( ( x >> 13 ) > 0 ) {
        //负数
        x += 0xc000;
    }
    if ( ( y >> 13 ) > 0 ) {
        //负数
        y += 0xc000;
    }
    //精度为0.1 时候
    //    x = static_cast< short int >( x / 10 );
    //    y = static_cast< short int >( x / 10 );

    int tag_id = ( static_cast< uchar >( data[ 13 ] ) & 0xf ) * 0x4000 * 0x4000 + static_cast< uchar >( data[ 14 ] ) * 0x80 * 0x4000 + static_cast< uchar >( data[ 15 ] ) * 0x4000
                 + static_cast< uchar >( data[ 16 ] ) * 0x80 + static_cast< uchar >( data[ 17 ] );
    int ang = static_cast< uchar >( data[ 10 ] ) * 0x80 + static_cast< uchar >( data[ 11 ] );
    // emit sigSendTips(QString("org x:%1 y:%2 rad:%3 id:%4").arg(x).arg(y).arg(ang).arg(tag_id));

    /********************摄像头X轴作为车头，摄像头配置软件角度设置为0********************/
    ang = 3600 - ang;  //先镜像反转
    if ( ang > 1800 )  //将角度从180~360转化成(-180，0]
    {
        ang = ang - 3600;
    }

    double rad = M_PI * ( static_cast< double >( ang ) ) / 1800;
    //偏差数据计算值异常，除去该数据
    if ( ( abs( x ) > 150 ) || ( abs( y ) > 150 ) ) {
        qCritical() << "坐标数据值异常!"
                    << "x:" << x << ";"
                    << "y:" << y << ";";
        return;
    }
    //使用于AGV 摄像头位置在中心位置  qrcode_to_mid：使用该参数来控制模块安装差异大的车
    if ( tag_id >= Param::qrcode_station_list.size() ) {

        qCritical() << "读取到的二维码超过设定的二维码最大数量列表!"
                    << "读到的id:" << tag_id << ";"
                    << "二维码最大数量:" << Param::qrcode_station_list.size() << ";";
        return;
    }
    qrcode_point.setRadian( rad );
    qrcode_point.setX( x + Param::qrcode_station_list.at( tag_id )->point()->x() - Param::qrcode_to_mid );
    qrcode_point.setY( y + Param::qrcode_station_list.at( tag_id )->point()->y() );

    qrcode_tag_id = tag_id;
    //如果不是同一个二维码,那么把二维码id记录下来
    if ( last_qrcode_tag_id != qrcode_tag_id ) {
        qDebug() << tr( "读取二维码 id:%1 x:%2 y:%3 rad:%4" ).arg( tag_id ).arg( qrcode_point.x() ).arg( qrcode_point.y() ).arg( qrcode_point.radian(), 0, 'f', 3 );
    }
    last_qrcode_tag_id = qrcode_tag_id;
    //将计算过好的导航需要的参数数据发送出去
    emit sigQrcodRecvieNaviParam();
}
